home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 22 / PCPP #22.iso / Quake2 / q2source_12_11 / utils3 / bsp / qrad3 / qrad3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-24  |  12.7 KB  |  698 lines

  1. // qrad.c
  2.  
  3. #include "qrad.h"
  4.  
  5.  
  6.  
  7. /*
  8.  
  9. NOTES
  10. -----
  11.  
  12. every surface must be divided into at least two patches each axis
  13.  
  14. */
  15.  
  16. patch_t        *face_patches[MAX_MAP_FACES];
  17. entity_t    *face_entity[MAX_MAP_FACES];
  18. patch_t        patches[MAX_PATCHES];
  19. unsigned    num_patches;
  20.  
  21. vec3_t        radiosity[MAX_PATCHES];        // light leaving a patch
  22. vec3_t        illumination[MAX_PATCHES];    // light arriving at a patch
  23.  
  24. vec3_t        face_offset[MAX_MAP_FACES];        // for rotating bmodels
  25. dplane_t    backplanes[MAX_MAP_PLANES];
  26.  
  27. char        inbase[32], outbase[32];
  28.  
  29. int            fakeplanes;                    // created planes for origin offset 
  30.  
  31. int        numbounce = 8;
  32. qboolean    extrasamples;
  33.  
  34. float    subdiv = 64;
  35. qboolean    dumppatches;
  36.  
  37. void BuildLightmaps (void);
  38. int TestLine (vec3_t start, vec3_t stop);
  39.  
  40. int        junk;
  41.  
  42. float    ambient = 0;
  43. float    maxlight = 196;
  44.  
  45. float    lightscale = 1.0;
  46.  
  47. qboolean    glview;
  48.  
  49. qboolean    nopvs;
  50.  
  51. char        source[1024];
  52.  
  53. float    direct_scale =    0.4;
  54. float    entity_scale =    1.0;
  55.  
  56. /*
  57. ===================================================================
  58.  
  59. MISC
  60.  
  61. ===================================================================
  62. */
  63.  
  64.  
  65. /*
  66. =============
  67. MakeBackplanes
  68. =============
  69. */
  70. void MakeBackplanes (void)
  71. {
  72.     int        i;
  73.  
  74.     for (i=0 ; i<numplanes ; i++)
  75.     {
  76.         backplanes[i].dist = -dplanes[i].dist;
  77.         VectorSubtract (vec3_origin, dplanes[i].normal, backplanes[i].normal);
  78.     }
  79. }
  80.  
  81. int        leafparents[MAX_MAP_LEAFS];
  82. int        nodeparents[MAX_MAP_NODES];
  83.  
  84. /*
  85. =============
  86. MakeParents
  87. =============
  88. */
  89. void MakeParents (int nodenum, int parent)
  90. {
  91.     int        i, j;
  92.     dnode_t    *node;
  93.  
  94.     nodeparents[nodenum] = parent;
  95.     node = &dnodes[nodenum];
  96.  
  97.     for (i=0 ; i<2 ; i++)
  98.     {
  99.         j = node->children[i];
  100.         if (j < 0)
  101.             leafparents[-j - 1] = nodenum;
  102.         else
  103.             MakeParents (j, nodenum);
  104.     }
  105. }
  106.  
  107.  
  108. /*
  109. ===================================================================
  110.  
  111. TRANSFER SCALES
  112.  
  113. ===================================================================
  114. */
  115.  
  116. int    PointInLeafnum (vec3_t point)
  117. {
  118.     int        nodenum;
  119.     vec_t    dist;
  120.     dnode_t    *node;
  121.     dplane_t    *plane;
  122.  
  123.     nodenum = 0;
  124.     while (nodenum >= 0)
  125.     {
  126.         node = &dnodes[nodenum];
  127.         plane = &dplanes[node->planenum];
  128.         dist = DotProduct (point, plane->normal) - plane->dist;
  129.         if (dist > 0)
  130.             nodenum = node->children[0];
  131.         else
  132.             nodenum = node->children[1];
  133.     }
  134.  
  135.     return -nodenum - 1;
  136. }
  137.  
  138.  
  139. dleaf_t        *PointInLeaf (vec3_t point)
  140. {
  141.     int        num;
  142.  
  143.     num = PointInLeafnum (point);
  144.     return &dleafs[num];
  145. }
  146.  
  147.  
  148. qboolean PvsForOrigin (vec3_t org, byte *pvs)
  149. {
  150.     dleaf_t    *leaf;
  151.  
  152.     if (!visdatasize)
  153.     {
  154.         memset (pvs, 255, (numleafs+7)/8 );
  155.         return true;
  156.     }
  157.  
  158.     leaf = PointInLeaf (org);
  159.     if (leaf->cluster == -1)
  160.         return false;        // in solid leaf
  161.  
  162.     DecompressVis (dvisdata + dvis->bitofs[leaf->cluster][DVIS_PVS], pvs);
  163.     return true;
  164. }
  165.  
  166.  
  167. /*
  168. =============
  169. MakeTransfers
  170.  
  171. =============
  172. */
  173. int    total_transfer;
  174.  
  175. void MakeTransfers (int i)
  176. {
  177.     int            j;
  178.     vec3_t        delta;
  179.     vec_t        dist, scale;
  180.     float        trans;
  181.     int            itrans;
  182.     patch_t        *patch, *patch2;
  183.     float        total;
  184.     dplane_t    plane;
  185.     vec3_t        origin;
  186.     float        transfers[MAX_PATCHES], *all_transfers;
  187.     int            s;
  188.     int            itotal;
  189.     byte        pvs[(MAX_MAP_LEAFS+7)/8];
  190.     int            cluster;
  191.  
  192.     patch = patches + i;
  193.     total = 0;
  194.  
  195.     VectorCopy (patch->origin, origin);
  196.     plane = *patch->plane;
  197.  
  198.     if (!PvsForOrigin (patch->origin, pvs))
  199.         return;
  200.  
  201.     // find out which patch2s will collect light
  202.     // from patch
  203.  
  204.     all_transfers = transfers;
  205.     patch->numtransfers = 0;
  206.     for (j=0, patch2 = patches ; j<num_patches ; j++, patch2++)
  207.     {
  208.         transfers[j] = 0;
  209.  
  210.         if (j == i)
  211.             continue;
  212.  
  213.         // check pvs bit
  214.         if (!nopvs)
  215.         {
  216.             cluster = patch2->cluster;
  217.             if (cluster == -1)
  218.                 continue;
  219.             if ( ! ( pvs[cluster>>3] & (1<<(cluster&7)) ) )
  220.                 continue;        // not in pvs
  221.         }
  222.  
  223.         // calculate vector
  224.         VectorSubtract (patch2->origin, origin, delta);
  225.         dist = VectorNormalize (delta, delta);
  226.         if (!dist)
  227.             continue;    // should never happen
  228.  
  229.         // reletive angles
  230.         scale = DotProduct (delta, plane.normal);
  231.         scale *= -DotProduct (delta, patch2->plane->normal);
  232.         if (scale <= 0)
  233.             continue;
  234.  
  235.         // check exact tramsfer
  236.         if (TestLine_r (0, patch->origin, patch2->origin) )
  237.             continue;
  238.  
  239.         trans = scale * patch2->area / (dist*dist);
  240.  
  241.         if (trans < 0)
  242.             trans = 0;        // rounding errors...
  243.  
  244.         transfers[j] = trans;
  245.         if (trans > 0)
  246.         {
  247.             total += trans;
  248.             patch->numtransfers++;
  249.         }
  250.     }
  251.  
  252.     // copy the transfers out and normalize
  253.     // total should be somewhere near PI if everything went right
  254.     // because partial occlusion isn't accounted for, and nearby
  255.     // patches have underestimated form factors, it will usually
  256.     // be higher than PI
  257.     if (patch->numtransfers)
  258.     {
  259.         transfer_t    *t;
  260.         
  261.         if (patch->numtransfers < 0 || patch->numtransfers > MAX_PATCHES)
  262.             Error ("Weird numtransfers");
  263.         s = patch->numtransfers * sizeof(transfer_t);
  264.         patch->transfers = malloc (s);
  265.         if (!patch->transfers)
  266.             Error ("Memory allocation failure");
  267.  
  268.         //
  269.         // normalize all transfers so all of the light
  270.         // is transfered to the surroundings
  271.         //
  272.         t = patch->transfers;
  273.         itotal = 0;
  274.         for (j=0 ; j<num_patches ; j++)
  275.         {
  276.             if (transfers[j] <= 0)
  277.                 continue;
  278.             itrans = transfers[j]*0x10000 / total;
  279.             itotal += itrans;
  280.             t->transfer = itrans;
  281.             t->patch = j;
  282.             t++;
  283.         }
  284.     }
  285.  
  286.     // don't bother locking around this.  not that important.
  287.     total_transfer += patch->numtransfers;
  288. }
  289.  
  290.  
  291. /*
  292. =============
  293. FreeTransfers
  294. =============
  295. */
  296. void FreeTransfers (void)
  297. {
  298.     int        i;
  299.  
  300.     for (i=0 ; i<num_patches ; i++)
  301.     {
  302.         free (patches[i].transfers);
  303.         patches[i].transfers = NULL;
  304.     }
  305. }
  306.  
  307.  
  308. //===================================================================
  309.  
  310. /*
  311. =============
  312. WriteWorld
  313. =============
  314. */
  315. void WriteWorld (char *name)
  316. {
  317.     int        i, j;
  318.     FILE        *out;
  319.     patch_t        *patch;
  320.     winding_t    *w;
  321.  
  322.     out = fopen (name, "w");
  323.     if (!out)
  324.         Error ("Couldn't open %s", name);
  325.  
  326.     for (j=0, patch=patches ; j<num_patches ; j++, patch++)
  327.     {
  328.         w = patch->winding;
  329.         fprintf (out, "%i\n", w->numpoints);
  330.         for (i=0 ; i<w->numpoints ; i++)
  331.         {
  332.             fprintf (out, "%5.2f %5.2f %5.2f %5.3f %5.3f %5.3f\n",
  333.                 w->p[i][0],
  334.                 w->p[i][1],
  335.                 w->p[i][2],
  336.                 patch->totallight[0],
  337.                 patch->totallight[1],
  338.                 patch->totallight[2]);
  339.         }
  340.         fprintf (out, "\n");
  341.     }
  342.  
  343.     fclose (out);
  344. }
  345.  
  346. /*
  347. =============
  348. WriteGlView
  349. =============
  350. */
  351. void WriteGlView (void)
  352. {
  353.     char    name[1024];
  354.     FILE    *f;
  355.     int        i, j;
  356.     patch_t    *p;
  357.     winding_t    *w;
  358.  
  359.     strcpy (name, source);
  360.     StripExtension (name);
  361.     strcat (name, ".glr");
  362.  
  363.     f = fopen (name, "w");
  364.     if (!f)
  365.         Error ("Couldn't open %s", f);
  366.  
  367.     for (j=0 ; j<num_patches ; j++)
  368.     {
  369.         p = &patches[j];
  370.         w = p->winding;
  371.         fprintf (f, "%i\n", w->numpoints);
  372.         for (i=0 ; i<w->numpoints ; i++)
  373.         {
  374.             fprintf (f, "%5.2f %5.2f %5.2f %5.3f %5.3f %5.3f\n",
  375.                 w->p[i][0],
  376.                 w->p[i][1],
  377.                 w->p[i][2],
  378.                 p->totallight[0]/128,
  379.                 p->totallight[1]/128,
  380.                 p->totallight[2]/128);
  381.         }
  382.         fprintf (f, "\n");
  383.     }
  384.  
  385.     fclose (f);
  386. }
  387.  
  388.  
  389. //==============================================================
  390.  
  391. /*
  392. =============
  393. CollectLight
  394. =============
  395. */
  396. float CollectLight (void)
  397. {
  398.     int        i, j;
  399.     patch_t    *patch;
  400.     vec_t    total;
  401.  
  402.     total = 0;
  403.  
  404.     for (i=0, patch=patches ; i<num_patches ; i++, patch++)
  405.     {
  406.         // skys never collect light, it is just dropped
  407.         if (patch->sky)
  408.         {
  409.             VectorClear (radiosity[i]);
  410.             VectorClear (illumination[i]);
  411.             continue;
  412.         }
  413.  
  414.         for (j=0 ; j<3 ; j++)
  415.         {
  416.             patch->totallight[j] += illumination[i][j] / patch->area;
  417.             radiosity[i][j] = illumination[i][j] * patch->reflectivity[j];
  418.         }
  419.  
  420.         total += radiosity[i][0] + radiosity[i][1] + radiosity[i][2];
  421.         VectorClear (illumination[i]);
  422.     }
  423.  
  424.     return total;
  425. }
  426.  
  427.  
  428. /*
  429. =============
  430. ShootLight
  431.  
  432. Send light out to other patches
  433.   Run multi-threaded
  434. =============
  435. */
  436. void ShootLight (int patchnum)
  437. {
  438.     int            k, l;
  439.     transfer_t    *trans;
  440.     int            num;
  441.     patch_t        *patch;
  442.     vec3_t        send;
  443.  
  444.     // this is the amount of light we are distributing
  445.     // prescale it so that multiplying by the 16 bit
  446.     // transfer values gives a proper output value
  447.     for (k=0 ; k<3 ; k++)
  448.         send[k] = radiosity[patchnum][k] / 0x10000;
  449.     patch = &patches[patchnum];
  450.  
  451.     trans = patch->transfers;
  452.     num = patch->numtransfers;
  453.  
  454.     for (k=0 ; k<num ; k++, trans++)
  455.     {
  456.         for (l=0 ; l<3 ; l++)
  457.             illumination[trans->patch][l] += send[l]*trans->transfer;
  458.     }
  459. }
  460.  
  461. /*
  462. =============
  463. BounceLight
  464. =============
  465. */
  466. void BounceLight (void)
  467. {
  468.     int        i, j;
  469.     float    added;
  470.     char    name[64];
  471.     patch_t    *p;
  472.  
  473.     for (i=0 ; i<num_patches ; i++)
  474.     {
  475.         p = &patches[i];
  476.         for (j=0 ; j<3 ; j++)
  477.         {
  478. //            p->totallight[j] = p->samplelight[j];
  479.             radiosity[i][j] = p->samplelight[j] * p->reflectivity[j] * p->area;
  480.         }
  481.     }
  482.  
  483.     for (i=0 ; i<numbounce ; i++)
  484.     {
  485.         RunThreadsOnIndividual (num_patches, false, ShootLight);
  486.         added = CollectLight ();
  487.  
  488.         qprintf ("bounce:%i added:%f\n", i, added);
  489.         if ( dumppatches && (i==0 || i == numbounce-1) )
  490.         {
  491.             sprintf (name, "bounce%i.txt", i);
  492.             WriteWorld (name);
  493.         }
  494.     }
  495. }
  496.  
  497.  
  498.  
  499. //==============================================================
  500.  
  501. void CheckPatches (void)
  502. {
  503.     int        i;
  504.     patch_t    *patch;
  505.  
  506.     for (i=0 ; i<num_patches ; i++)
  507.     {
  508.         patch = &patches[i];
  509.         if (patch->totallight[0] < 0 || patch->totallight[1] < 0 || patch->totallight[2] < 0)
  510.             Error ("negative patch totallight\n");
  511.     }
  512. }
  513.  
  514. /*
  515. =============
  516. RadWorld
  517. =============
  518. */
  519. void RadWorld (void)
  520. {
  521.     if (numnodes == 0 || numfaces == 0)
  522.         Error ("Empty map");
  523.     MakeBackplanes ();
  524.     MakeParents (0, -1);
  525.     MakeTnodes (&dmodels[0]);
  526.  
  527.     // turn each face into a single patch
  528.     MakePatches ();
  529.  
  530.     // subdivide patches to a maximum dimension
  531.     SubdividePatches ();
  532.  
  533.     // create directlights out of patches and lights
  534.     CreateDirectLights ();
  535.  
  536.     // build initial facelights
  537.     RunThreadsOnIndividual (numfaces, true, BuildFacelights);
  538.  
  539.     if (numbounce > 0)
  540.     {
  541.         // build transfer lists
  542.         RunThreadsOnIndividual (num_patches, true, MakeTransfers);
  543.         qprintf ("transfer lists: %5.1f megs\n"
  544.         , (float)total_transfer * sizeof(transfer_t) / (1024*1024));
  545.  
  546.         // spread light around
  547.         BounceLight ();
  548.         
  549.         FreeTransfers ();
  550.  
  551.         CheckPatches ();
  552.     }
  553.  
  554.     if (glview)
  555.         WriteGlView ();
  556.  
  557.     // blend bounced light into direct light and save
  558.     PairEdges ();
  559.     LinkPlaneFaces ();
  560.  
  561.     lightdatasize = 0;
  562.     RunThreadsOnIndividual (numfaces, true, FinalLightFace);
  563. }
  564.  
  565.  
  566. /*
  567. ========
  568. main
  569.  
  570. light modelfile
  571. ========
  572. */
  573. int main (int argc, char **argv)
  574. {
  575.     int        i;
  576.     double        start, end;
  577.     char        name[1024];
  578.  
  579.     printf ("----- Radiosity ----\n");
  580.  
  581.     verbose = false;
  582.  
  583.     for (i=1 ; i<argc ; i++)
  584.     {
  585.         if (!strcmp(argv[i],"-dump"))
  586.             dumppatches = true;
  587.         else if (!strcmp(argv[i],"-bounce"))
  588.         {
  589.             numbounce = atoi (argv[i+1]);
  590.             i++;
  591.         }
  592.         else if (!strcmp(argv[i],"-v"))
  593.         {
  594.             verbose = true;
  595.         }
  596.         else if (!strcmp(argv[i],"-extra"))
  597.         {
  598.             extrasamples = true;
  599.             printf ("extrasamples = true\n");
  600.         }
  601.         else if (!strcmp(argv[i],"-threads"))
  602.         {
  603.             numthreads = atoi (argv[i+1]);
  604.             i++;
  605.         }
  606.         else if (!strcmp(argv[i],"-chop"))
  607.         {
  608.             subdiv = atoi (argv[i+1]);
  609.             i++;
  610.         }
  611.         else if (!strcmp(argv[i],"-scale"))
  612.         {
  613.             lightscale = atof (argv[i+1]);
  614.             i++;
  615.         }
  616.         else if (!strcmp(argv[i],"-direct"))
  617.         {
  618.             direct_scale *= atof(argv[i+1]);
  619.             printf ("direct light scaling at %f\n", direct_scale);
  620.             i++;
  621.         }
  622.         else if (!strcmp(argv[i],"-entity"))
  623.         {
  624.             entity_scale *= atof(argv[i+1]);
  625.             printf ("entity light scaling at %f\n", entity_scale);
  626.             i++;
  627.         }
  628.         else if (!strcmp(argv[i],"-glview"))
  629.         {
  630.             glview = true;
  631.             printf ("glview = true\n");
  632.         }
  633.         else if (!strcmp(argv[i],"-nopvs"))
  634.         {
  635.             nopvs = true;
  636.             printf ("nopvs = true\n");
  637.         }
  638.         else if (!strcmp(argv[i],"-ambient"))
  639.         {
  640.             ambient = atof (argv[i+1]) * 128;
  641.             i++;
  642.         }
  643.         else if (!strcmp(argv[i],"-maxlight"))
  644.         {
  645.             maxlight = atof (argv[i+1]) * 128;
  646.             i++;
  647.         }
  648.         else if (!strcmp (argv[i],"-tmpin"))
  649.             strcpy (inbase, "/tmp");
  650.         else if (!strcmp (argv[i],"-tmpout"))
  651.             strcpy (outbase, "/tmp");
  652.         else
  653.             break;
  654.     }
  655.  
  656.     ThreadSetDefault ();
  657.  
  658.     if (maxlight > 255)
  659.         maxlight = 255;
  660.  
  661.     if (i != argc - 1)
  662.         Error ("usage: qrad [-v] [-chop num] [-scale num] [-ambient num] [-maxlight num] [-threads num] bspfile");
  663.  
  664.     start = I_FloatTime ();
  665.  
  666.     SetQdirFromPath (argv[i]);    
  667.     strcpy (source, ExpandArg(argv[i]));
  668.     StripExtension (source);
  669.     DefaultExtension (source, ".bsp");
  670.  
  671. //    ReadLightFile ();
  672.  
  673.     sprintf (name, "%s%s", inbase, source);
  674.     printf ("reading %s\n", name);
  675.     LoadBSPFile (name);
  676.     ParseEntities ();
  677.     CalcTextureReflectivity ();
  678.  
  679.     if (!visdatasize)
  680.     {
  681.         printf ("No vis information, direct lighting only.\n");
  682.         numbounce = 0;
  683.         ambient = 0.1;
  684.     }
  685.  
  686.     RadWorld ();
  687.  
  688.     sprintf (name, "%s%s", outbase, source);
  689.     printf ("writing %s\n", name);
  690.     WriteBSPFile (name);
  691.  
  692.     end = I_FloatTime ();
  693.     printf ("%5.0f seconds elapsed\n", end-start);
  694.     
  695.     return 0;
  696. }
  697.  
  698.